﻿using System.Text;
using HK.Core.Common.Data;
using HK.Core.Encryption.Protocol;
using HK.Core.IO.Protocol.Output;
using HK.Core.Utils;

namespace HK.Core.IO.Output
{
    /// <summary>
    /// 加密文件I/O协议
    /// </summary>
    /// <typeparam name="TData">数据类型</typeparam>
    public class TokenFileIO<TData> : FileIO<TData>, ITokenFileIO<TData>
        where TData : JsonData, IToken
    {
        
#region Create

        /// <summary>
        /// 创建加密文件I/O对象
        /// </summary>
        /// <param name="iJson">Json数据对象</param>
        /// <param name="iEncoding">字节编码</param>
        /// <param name="iPath">路径</param>
        /// <param name="iSecretKey">路径</param>
        /// <param name="iAlgorithms">Token算法</param>
        /// <typeparam name="TData">数据类型</typeparam>
        /// <returns>加密文件I/O对象</returns>
        public static TokenFileIO<TData> Create<TData>(TData iJson, Encoding iEncoding, 
            string iPath, string iSecretKey = null, TokenAlgorithms iAlgorithms = TokenAlgorithms.Hs256)
            where TData : JsonData, IToken
        {
            return new TokenFileIO<TData>
            {
                Mode = FileIoMode.Json, Data = iJson, Encoding = iEncoding, Path = iPath,
                SecretKey = iSecretKey, Algorithms = iAlgorithms
            };
        }

#endregion
        
        /// <summary>
        /// 保护构造函数
        /// </summary>
        private TokenFileIO() {}
        
        /// <summary>
        /// Token算法
        /// </summary>
        public TokenAlgorithms Algorithms { get; private set; } = TokenAlgorithms.Hs256;

        /// <summary>
        /// 密钥
        /// </summary>
        public string SecretKey { get; private set; } = null;

#region Import

        /// <summary>
        /// 执行导入
        /// </summary>
        /// <returns>true:OK; false:NG;</returns>
        protected override bool DoImport()
        {
            var tokenStr = System.IO.File.ReadAllText(Path);
            if (string.IsNullOrEmpty(tokenStr)) return false;

            var status = UtilsToken.Decode(tokenStr, Encoding, out TData oData, SecretKey, true);
            if (UtilsToken.VerifyStatus.Ok != status || default(TData) == oData || !oData.Valid) return false;

            // 数据
            Data = oData;
            return true;
        }

#endregion

#region Export
        
        /// <summary>
        /// 执行导入
        /// </summary>
        /// <returns>true:OK; false:NG;</returns>
        protected override bool DoExport()
        {
            var token = UtilsToken.Encode(Data, Encoding, SecretKey, Algorithms);
            if (string.IsNullOrEmpty(token)) return false;

            // 写入文本
            if (!UtilsIo.WriteTxtFile(Path, token, true))
            {
                Error("DoExport():UtilsIo.WriteTxtFile() Failed!(Path:{0})", Path);
                return false;
            }
            return true;
        }

#endregion


    }
}